🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / settings / src / commonMain / kotlin / org / meshtastic / feature / settings / debugging / DebugViewModel.kt
Displaying Raw • Download
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/debugging/DebugViewModel.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 23.72 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.settings.debugging
Tff7b72import T7ee787androidx.compose.runtime.Immutable
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.collections.immutable.ImmutableList
Tff7b72import T7ee787kotlinx.collections.immutable.persistentListOf
Tff7b72import T7ee787kotlinx.collections.immutable.toImmutableList
Tff7b72import T7ee787kotlinx.coroutines.FlowPreview
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.debounce
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787kotlinx.coroutines.flow.mapLatest
Tff7b72import T7ee787kotlinx.coroutines.withContext
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.util.DateFormatter
Tff7b72import T7ee787org.meshtastic.core.common.util.MetricFormatter
Tff7b72import T7ee787org.meshtastic.core.common.util.ioDispatcher
Tff7b72import T7ee787org.meshtastic.core.common.util.nowInstant
Tff7b72import T7ee787org.meshtastic.core.database.entity.Packet
Tff7b72import T7ee787org.meshtastic.core.model.MeshLog
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.getTracerouteResponse
Tff7b72import T7ee787org.meshtastic.core.model.util.decodeOrNull
Tff7b72import T7ee787org.meshtastic.core.model.util.toReadableString
Tff7b72import T7ee787org.meshtastic.core.repository.MeshLogPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.MeshLogRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.debug_clear
Tff7b72import T7ee787org.meshtastic.core.resources.debug_clear_logs_confirm
Tff7b72import T7ee787org.meshtastic.core.ui.util.AlertManager
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.safeLaunch
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
Tff7b72import T7ee787org.meshtastic.proto.AdminMessage
Tff7b72import T7ee787org.meshtastic.proto.MeshPacket
Tff7b72import T7ee787org.meshtastic.proto.NeighborInfo
Tff7b72import T7ee787org.meshtastic.proto.Paxcount
Tff7b72import T7ee787org.meshtastic.proto.PortNum
Tff7b72import T7ee787org.meshtastic.proto.Position
Tff7b72import T7ee787org.meshtastic.proto.RouteDiscovery
Tff7b72import T7ee787org.meshtastic.proto.Routing
Tff7b72import T7ee787org.meshtastic.proto.StoreAndForward
Tff7b72import T7ee787org.meshtastic.proto.StoreForwardPlusPlus
Tff7b72import T7ee787org.meshtastic.proto.Telemetry
Tff7b72import T7ee787org.meshtastic.proto.User
Tff7b72import T7ee787org.meshtastic.proto.Waypoint
Tff7b72enum Tff7b72class T56d364FilterMode Tb4b4b4{
Te6edf3ANDTb4b4b4,
Te6edf3ORTb4b4b4,
Tb4b4b4}
T8b949e// --- Search and Filter Managers ---
Tff7b72class T56d364LogSearchManager Tb4b4b4{
Tff7b72data Tff7b72class T56d364SearchMatchTb4b4b4(Tff7b72val Te6edf3logIndexTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3startTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3endTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3fieldTb4b4b4: Tffa657StringTb4b4b4)
Tff7b72data Tff7b72class T56d364SearchStateTb4b4b4(
Tff7b72val Te6edf3searchTextTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Tff7b72val Te6edf3currentMatchIndexTb4b4b4: Tffa657Int Tff7b72= Tff7b72-T79c0ff1Tb4b4b4,
Tff7b72val Te6edf3allMatchesTb4b4b4: Te6edf3ListTff7b72<Te6edf3SearchMatchTff7b72> Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72val Te6edf3hasMatchesTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_searchText Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3searchText Tff7b72= Te6edf3_searchTextTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_currentMatchIndex Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72-T79c0ff1Tb4b4b4)
Tff7b72val Te6edf3currentMatchIndex Tff7b72= Te6edf3_currentMatchIndexTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_searchState Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3SearchStateTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3searchState Tff7b72= Te6edf3_searchStateTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffsetSearchTextTb4b4b4(Te6edf3textTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3_searchTextTb4b4b4.Te6edf3value Tff7b72= Te6edf3text
Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72= Tff7b72-T79c0ff1
Tb4b4b4}
Tff7b72fun Td2a8ffgoToNextMatchTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3matches Tff7b72= Te6edf3_searchStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3allMatches
Tff7b72if Tb4b4b4(Te6edf3matchesTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nextIndex Tff7b72= Tff7b72if Tb4b4b4(Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72< Te6edf3matchesTb4b4b4.Te6edf3lastIndexTb4b4b4) Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72+ T79c0ff1 Tff7b72else T79c0ff0
Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72= Te6edf3nextIndex
Te6edf3_searchStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3_searchStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3currentMatchIndex Tff7b72= Te6edf3nextIndexTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffgoToPreviousMatchTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3matches Tff7b72= Te6edf3_searchStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3allMatches
Tff7b72if Tb4b4b4(Te6edf3matchesTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3prevIndex Tff7b72= Tff7b72if Tb4b4b4(Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72> T79c0ff0Tb4b4b4) Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72- T79c0ff1 Tff7b72else Te6edf3matchesTb4b4b4.Te6edf3lastIndex
Te6edf3_currentMatchIndexTb4b4b4.Te6edf3value Tff7b72= Te6edf3prevIndex
Te6edf3_searchStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3_searchStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3currentMatchIndex Tff7b72= Te6edf3prevIndexTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffclearSearchTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3setSearchTextTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffupdateMatchesTb4b4b4(Te6edf3searchTextTb4b4b4: Tffa657StringTb4b4b4, Te6edf3filteredLogsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72>Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3matches Tff7b72= Te6edf3findSearchMatchesTb4b4b4(Te6edf3searchTextTb4b4b4, Te6edf3filteredLogsTb4b4b4)
Tff7b72val Te6edf3hasMatches Tff7b72= Te6edf3matchesTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)
Te6edf3_searchStateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3_searchStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3searchText Tff7b72= Te6edf3searchTextTb4b4b4,
Te6edf3allMatches Tff7b72= Te6edf3matchesTb4b4b4,
Te6edf3hasMatches Tff7b72= Te6edf3hasMatchesTb4b4b4,
Te6edf3currentMatchIndex Tff7b72= Tff7b72if Tb4b4b4(Te6edf3hasMatchesTb4b4b4) Te6edf3_currentMatchIndexTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3coerceInTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3matchesTb4b4b4.Te6edf3lastIndexTb4b4b4) Tff7b72else Tff7b72-T79c0ff1Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8fffindSearchMatchesTb4b4b4(Te6edf3searchTextTb4b4b4: Tffa657StringTb4b4b4, Te6edf3filteredLogsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3SearchMatchTff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3searchTextTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3emptyListTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3filteredLogs
Tb4b4b4.Te6edf3flatMapIndexed Tb4b4b4{ Te6edf3logIndexTb4b4b4, Te6edf3log Tff7b72-Tff7b72>
Te6edf3searchTextTb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3flatMap Tb4b4b4{ Te6edf3term Tff7b72-Tff7b72>
Tff7b72val Te6edf3escapedTerm Tff7b72= Te6edf3RegexTb4b4b4.Te6edf3escapeTb4b4b4(Te6edf3termTb4b4b4)
Tff7b72val Te6edf3regex Tff7b72= Te6edf3escapedTermTb4b4b4.Te6edf3toRegexTb4b4b4(Te6edf3RegexOptionTb4b4b4.Te6edf3IGNORE_CASETb4b4b4)
Tff7b72val Te6edf3messageMatches Tff7b72=
Te6edf3regexTb4b4b4.Te6edf3findAllTb4b4b4(Te6edf3logTb4b4b4.Te6edf3logMessageTb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3SearchMatchTb4b4b4(Te6edf3logIndexTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3firstTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3lastTb4b4b4, Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3typeMatches Tff7b72=
Te6edf3regexTb4b4b4.Te6edf3findAllTb4b4b4(Te6edf3logTb4b4b4.Te6edf3messageTypeTb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3SearchMatchTb4b4b4(Te6edf3logIndexTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3firstTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3lastTb4b4b4, Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3dateMatches Tff7b72=
Te6edf3regexTb4b4b4.Te6edf3findAllTb4b4b4(Te6edf3logTb4b4b4.Te6edf3formattedReceivedDateTb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3SearchMatchTb4b4b4(Te6edf3logIndexTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3firstTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3lastTb4b4b4, Ta5d6ff"Ta5d6ffdateTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3decodedPayloadMatches Tff7b72=
Te6edf3logTb4b4b4.Te6edf3decodedPayloadTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3regexTb4b4b4.Te6edf3findAllTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3SearchMatchTb4b4b4(Te6edf3logIndexTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3firstTb4b4b4, Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3lastTb4b4b4, Ta5d6ff"Ta5d6ffdecodedPayloadTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4} Tff7b72?: Te6edf3emptySequenceTb4b4b4(Tb4b4b4)
Te6edf3messageMatches Tff7b72+ Te6edf3typeMatches Tff7b72+ Te6edf3dateMatches Tff7b72+ Te6edf3decodedPayloadMatches
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3sortedBy Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3start Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72class T56d364LogFilterManager Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3_filterTexts Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3ListTff7b72<Tffa657StringTff7b72>Tff7b72>Tb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3filterTexts Tff7b72= Te6edf3_filterTextsTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_filteredLogs Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72>Tff7b72>Tb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3filteredLogs Tff7b72= Te6edf3_filteredLogsTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffsetFilterTextsTb4b4b4(Te6edf3filtersTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3_filterTextsTb4b4b4.Te6edf3value Tff7b72= Te6edf3filters
Tb4b4b4}
Tff7b72fun Td2a8ffupdateFilteredLogsTb4b4b4(Te6edf3logsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3_filteredLogsTb4b4b4.Te6edf3value Tff7b72= Te6edf3logs
Tb4b4b4}
Tff7b72fun Td2a8fffilterLogsTb4b4b4(
Te6edf3logsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72>Tb4b4b4,
Te6edf3filterTextsTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4,
Te6edf3filterModeTb4b4b4: Te6edf3FilterModeTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3DebugViewModelTb4b4b4.Te6edf3UiMeshLogTff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3filterTextsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return Te6edf3logs
Tff7b72return Te6edf3logsTb4b4b4.Te6edf3filter Tb4b4b4{ Te6edf3logItem Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4(Te6edf3filterModeTb4b4b4) Tb4b4b4{
Te6edf3FilterModeTb4b4b4.Te6edf3OR Tff7b72-Tff7b72>
Te6edf3filterTextsTb4b4b4.Te6edf3any Tb4b4b4{ Te6edf3filter Tff7b72-Tff7b72>
Te6edf3logItemTb4b4b4.Te6edf3logMessageTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Te6edf3logItemTb4b4b4.Te6edf3messageTypeTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Te6edf3logItemTb4b4b4.Te6edf3formattedReceivedDateTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Tb4b4b4(Te6edf3logItemTb4b4b4.Te6edf3decodedPayloadTff7b72?.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72=Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Te6edf3FilterModeTb4b4b4.Te6edf3AND Tff7b72-Tff7b72>
Te6edf3filterTextsTb4b4b4.Te6edf3all Tb4b4b4{ Te6edf3filter Tff7b72-Tff7b72>
Te6edf3logItemTb4b4b4.Te6edf3logMessageTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Te6edf3logItemTb4b4b4.Te6edf3messageTypeTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Te6edf3logItemTb4b4b4.Te6edf3formattedReceivedDateTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72|Tff7b72|
Tb4b4b4(Te6edf3logItemTb4b4b4.Te6edf3decodedPayloadTff7b72?.Te6edf3containsTb4b4b4(Te6edf3filterTb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tff7b72=Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Throttle for the expensive mesh-log decode pipeline (see [DebugViewModel.meshLog]). Chosen to stay well under human
* perception for a debug log view while bounding decode frequency during a packet flood; not a correctness requirement,
* just a GC-thrash guard.
*/
Tff7b72private Tff7b72const Tff7b72val Te6edf3LOG_DECODE_DEBOUNCE_MS Tff7b72= T79c0ff2T79c0ff0T79c0ff0L
Tf0883e@KoinViewModel
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tff7b72class T56d364DebugViewModelTb4b4b4(
Tff7b72private Tff7b72val Te6edf3meshLogRepositoryTb4b4b4: Te6edf3MeshLogRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3meshLogPrefsTb4b4b4: Te6edf3MeshLogPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3alertManagerTb4b4b4: Te6edf3AlertManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3dispatchersTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3diTb4b4b4.Te6edf3CoroutineDispatchersTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tf0883e@OptInTb4b4b4(Te6edf3FlowPreviewTff7b72::Te6edf3classTb4b4b4)
Tff7b72val Te6edf3meshLogTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ImmutableListTff7b72<Te6edf3UiMeshLogTff7b72>Tff7b72> Tff7b72=
Te6edf3meshLogRepository
Tb4b4b4.Te6edf3getAllLogsTb4b4b4(Tb4b4b4)
T8b949e// Room re-emits this Flow on every insert into the mesh_log table. Under a packet
T8b949e// flood (hostile mesh traffic, a runaway sender, etc.) that can fire many times a
T8b949e// second; without throttling, mapLatest keeps restarting a full re-decode of up to
T8b949e// DEFAULT_MAX_LOGS (5000) rows -- including proto toString() + node-DB lookups --
T8b949e// faster than it can complete, thrashing the GC instead of making progress.
T8b949e// Debouncing caps the decode rate independent of the insert rate.
Tb4b4b4.Te6edf3debounceTb4b4b4(Te6edf3LOG_DECODE_DEBOUNCE_MSTb4b4b4)
Tb4b4b4.Te6edf3mapLatest Tb4b4b4{ Te6edf3logs Tff7b72-Tff7b72> Te6edf3withContextTb4b4b4(Te6edf3dispatchersTb4b4b4.Te6edf3defaultTb4b4b4) Tb4b4b4{ Te6edf3toUiStateTb4b4b4(Te6edf3logsTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3persistentListOfTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_retentionDays Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3meshLogPrefsTb4b4b4.Te6edf3retentionDaysTb4b4b4.Te6edf3valueTb4b4b4)
Tff7b72val Te6edf3retentionDaysTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3_retentionDaysTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_loggingEnabled Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3meshLogPrefsTb4b4b4.Te6edf3loggingEnabledTb4b4b4.Te6edf3valueTb4b4b4)
Tff7b72val Te6edf3loggingEnabledTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3_loggingEnabledTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
T8b949e// --- Managers ---
Tff7b72val Te6edf3searchManager Tff7b72= Te6edf3LogSearchManagerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3filterManager Tff7b72= Te6edf3LogFilterManagerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3searchText
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3searchManagerTb4b4b4.Te6edf3searchText
Tff7b72val Te6edf3currentMatchIndex
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3searchManagerTb4b4b4.Te6edf3currentMatchIndex
Tff7b72val Te6edf3searchState
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3searchManagerTb4b4b4.Te6edf3searchState
Tff7b72val Te6edf3filterTexts
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3filterManagerTb4b4b4.Te6edf3filterTexts
Tff7b72val Te6edf3filteredLogs
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3filterManagerTb4b4b4.Te6edf3filteredLogs
Tff7b72private Tff7b72val Te6edf3_selectedLogId Tff7b72= Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3selectedLogId Tff7b72= Te6edf3_selectedLogIdTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffupdateFilteredLogsTb4b4b4(Te6edf3logsTb4b4b4: Te6edf3ListTff7b72<Te6edf3UiMeshLogTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3filterManagerTb4b4b4.Te6edf3updateFilteredLogsTb4b4b4(Te6edf3logsTb4b4b4)
Te6edf3searchManagerTb4b4b4.Te6edf3updateMatchesTb4b4b4(Te6edf3searchManagerTb4b4b4.Te6edf3searchTextTb4b4b4.Te6edf3valueTb4b4b4, Te6edf3logsTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffsetRetentionDaysTb4b4b4(Te6edf3daysTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3clamped Tff7b72= Te6edf3daysTb4b4b4.Te6edf3coerceInTb4b4b4(Te6edf3MeshLogPrefsTb4b4b4.Te6edf3MIN_RETENTION_DAYSTb4b4b4, Te6edf3MeshLogPrefsTb4b4b4.Te6edf3MAX_RETENTION_DAYSTb4b4b4)
Te6edf3meshLogPrefsTb4b4b4.Te6edf3setRetentionDaysTb4b4b4(Te6edf3clampedTb4b4b4)
Te6edf3_retentionDaysTb4b4b4.Te6edf3value Tff7b72= Te6edf3clamped
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetRetentionDaysTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteLogsOlderThanTb4b4b4(Te6edf3clampedTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetLoggingEnabledTb4b4b4(Te6edf3enabledTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3meshLogPrefsTb4b4b4.Te6edf3setLoggingEnabledTb4b4b4(Te6edf3enabledTb4b4b4)
Te6edf3_loggingEnabledTb4b4b4.Te6edf3value Tff7b72= Te6edf3enabled
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3enabledTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffdisableLoggingTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteAllTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffenableLoggingTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteLogsOlderThanTb4b4b4(Te6edf3meshLogPrefsTb4b4b4.Te6edf3retentionDaysTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72suspend Tff7b72fun Td2a8ffloadLogsForExportTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ImmutableListTff7b72<Te6edf3UiMeshLogTff7b72> Tff7b72= Te6edf3withContextTb4b4b4(Te6edf3ioDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3unbounded Tff7b72= Te6edf3meshLogRepositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3logs Tff7b72= Tff7b72if Tb4b4b4(Te6edf3unboundedTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3meshLogRepositoryTb4b4b4.Te6edf3getAllLogsTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4) Tff7b72else Te6edf3unbounded
Te6edf3toUiStateTb4b4b4(Te6edf3logsTb4b4b4)
Tb4b4b4}
Tff7b72init Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffDebugViewModel createdTa5d6ff" Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsearchMatchUpdaterTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3combineTb4b4b4(Te6edf3searchManagerTb4b4b4.Te6edf3searchTextTb4b4b4, Te6edf3filterManagerTb4b4b4.Te6edf3filteredLogsTb4b4b4) Tb4b4b4{ Te6edf3searchTextTb4b4b4, Te6edf3logs Tff7b72-Tff7b72>
Te6edf3searchManagerTb4b4b4.Te6edf3findSearchMatchesTb4b4b4(Te6edf3searchTextTb4b4b4, Te6edf3logsTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3collect Tb4b4b4{
Te6edf3searchManagerTb4b4b4.Te6edf3updateMatchesTb4b4b4(Te6edf3searchManagerTb4b4b4.Te6edf3searchTextTb4b4b4.Te6edf3valueTb4b4b4, Te6edf3filterManagerTb4b4b4.Te6edf3filteredLogsTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonClearedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onClearedTb4b4b4(Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffDebugViewModel clearedTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fftoUiStateTb4b4b4(Te6edf3databaseLogsTb4b4b4: Te6edf3ListTff7b72<Te6edf3MeshLogTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3ImmutableListTff7b72<Te6edf3UiMeshLogTff7b72> Tb4b4b4{
T8b949e// Snapshot the node DB once per decode pass, not once per row. With up to
T8b949e// DEFAULT_MAX_LOGS (5000) rows and meshes that can carry hundreds/thousands of nodes
T8b949e// (see push_fake_nodedb), re-materializing `nodeDBbyNum.values.toList()` inside the
T8b949e// per-row loop was an O(rows * nodes) hotspot that compounded the flood-induced
T8b949e// re-decode thrash described above.
Tff7b72val Te6edf3nodeList Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3toListTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3myNodeNum Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNum
Tff7b72return Te6edf3databaseLogs
Tb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3UiMeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Tffa657itTb4b4b4.Te6edf3uuidTb4b4b4,
Te6edf3messageType Tff7b72= Tffa657itTb4b4b4.Te6edf3message_typeTb4b4b4,
Te6edf3formattedReceivedDate Tff7b72= Te6edf3DateFormatterTb4b4b4.Te6edf3formatDateTimeTb4b4b4(Tffa657itTb4b4b4.Te6edf3received_dateTb4b4b4)Tb4b4b4,
Te6edf3logMessage Tff7b72= Te6edf3annotateMeshLogMessageTb4b4b4(Tffa657itTb4b4b4, Te6edf3nodeListTb4b4b4, Te6edf3myNodeNumTb4b4b4)Tb4b4b4,
Te6edf3decodedPayload Tff7b72= Te6edf3decodePayloadFromMeshLogTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3toImmutableListTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/** Transform the input [MeshLog] by enhancing the raw message with annotations. */
Tff7b72private Tff7b72fun Td2a8ffannotateMeshLogMessageTb4b4b4(Te6edf3meshLogTb4b4b4: Te6edf3MeshLogTb4b4b4, Te6edf3nodeListTb4b4b4: Te6edf3ListTff7b72<Te6edf3NodeTff7b72>Tb4b4b4, Te6edf3myNodeNumTb4b4b4: Tffa657Int?Tb4b4b4)Tb4b4b4: Tffa657String Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3meshLogTb4b4b4.Te6edf3message_typeTb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffLogRecordTa5d6ff" Tff7b72-Tff7b72> Te6edf3meshLogTb4b4b4.Te6edf3fromRadioTb4b4b4.Te6edf3log_recordTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff"Ta5d6ff\\Ta5d6ffnTa5d6ff\"Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff\"Ta5d6ff"Tb4b4b4)
Ta5d6ff"Ta5d6ffPacketTa5d6ff" Tff7b72-Tff7b72>
Te6edf3meshLogTb4b4b4.Te6edf3meshPacketTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3packet Tff7b72-Tff7b72> Te6edf3annotatePacketLogTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3nodeListTb4b4b4, Te6edf3myNodeNumTb4b4b4) Tb4b4b4}
Tff7b72?: Te6edf3meshLogTb4b4b4.Te6edf3raw_message
Ta5d6ff"Ta5d6ffNodeInfoTa5d6ff" Tff7b72-Tff7b72>
Te6edf3meshLogTb4b4b4.Te6edf3nodeInfoTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3nodeInfo Tff7b72-Tff7b72> Te6edf3annotateRawMessageTb4b4b4(Te6edf3meshLogTb4b4b4.Te6edf3raw_messageTb4b4b4, Te6edf3nodeInfoTb4b4b4.Te6edf3numTb4b4b4) Tb4b4b4}
Tff7b72?: Te6edf3meshLogTb4b4b4.Te6edf3raw_message
Ta5d6ff"Ta5d6ffMyNodeInfoTa5d6ff" Tff7b72-Tff7b72>
Te6edf3meshLogTb4b4b4.Te6edf3myNodeInfoTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3nodeInfo Tff7b72-Tff7b72> Te6edf3annotateRawMessageTb4b4b4(Te6edf3meshLogTb4b4b4.Te6edf3raw_messageTb4b4b4, Te6edf3nodeInfoTb4b4b4.Te6edf3my_node_numTb4b4b4) Tb4b4b4}
Tff7b72?: Te6edf3meshLogTb4b4b4.Te6edf3raw_message
Tff7b72else Tff7b72-Tff7b72> Te6edf3meshLogTb4b4b4.Te6edf3raw_message
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffannotatePacketLogTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4, Te6edf3nodeListTb4b4b4: Te6edf3ListTff7b72<Te6edf3NodeTff7b72>Tb4b4b4, Te6edf3myNodeNumTb4b4b4: Tffa657Int?Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3decoded Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decoded
Tff7b72val Te6edf3basePacket Tff7b72= Te6edf3packetTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3decoded Tff7b72= Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3baseText Tff7b72= Te6edf3basePacketTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3trimEndTb4b4b4(Tb4b4b4)
Tff7b72var Te6edf3result Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3decoded Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3decodedText Tff7b72= Te6edf3decodedTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3trimEndTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3prependIndentTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)
Ta5d6ff"Tffd700$Te6edf3baseTextTa5d6ff\Ta5d6ffndecoded {Ta5d6ff\Ta5d6ffnTffd700$Te6edf3decodedTextTa5d6ff\Ta5d6ffn}Ta5d6ff"
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3baseText
Tb4b4b4}
Tff7b72val Te6edf3relayNode Tff7b72= Te6edf3packetTb4b4b4.Te6edf3relay_node
Tff7b72var Te6edf3relayNodeAnnotationTb4b4b4: Tffa657String? Tff7b72= Tff7b72null
Tff7b72val Te6edf3placeholder Tff7b72= Ta5d6ff"Ta5d6ff___RELAY_NODE___Ta5d6ff"
Tff7b72if Tb4b4b4(Te6edf3relayNode Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3PacketTb4b4b4.Te6edf3getRelayNodeTb4b4b4(Te6edf3relayNodeTb4b4b4, Te6edf3nodeListTb4b4b4, Te6edf3myNodeNumTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72val Te6edf3relayId Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3id
Tff7b72val Te6edf3relayName Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_name
Tff7b72val Te6edf3regex Tff7b72= Te6edf3RegexTb4b4b4(Ta5d6ff"""Ta5d6ff\Ta5d6ffbrelay_node: Tffd700${Te6edf3relayNodeTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff\Ta5d6ffbTa5d6ff"""Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3regexTb4b4b4.Te6edf3containsMatchInTb4b4b4(Te6edf3resultTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3relayNodeAnnotation Tff7b72= Ta5d6ff"Ta5d6ffrelay_node: Tffd700$Te6edf3relayNameTa5d6ff (Tffd700$Te6edf3relayIdTa5d6ff)Ta5d6ff"
Te6edf3result Tff7b72= Te6edf3regexTb4b4b4.Te6edf3replaceTb4b4b4(Te6edf3resultTb4b4b4, Te6edf3placeholderTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3result Tff7b72= Te6edf3annotateRawMessageTb4b4b4(Te6edf3resultTb4b4b4, Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3packetTb4b4b4.Te6edf3toTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3relayNodeAnnotation Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3result Tff7b72= Te6edf3resultTb4b4b4.Te6edf3replaceTb4b4b4(Te6edf3placeholderTb4b4b4, Te6edf3relayNodeAnnotationTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Not annotated with name, so use hex.
Te6edf3result Tff7b72= Te6edf3annotateRawMessageTb4b4b4(Te6edf3resultTb4b4b4, Te6edf3relayNodeTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3result
Tb4b4b4}
T8b949e/** Annotate the raw message string with the node IDs provided, in hex, if they are present. */
Tff7b72private Tff7b72fun Td2a8ffannotateRawMessageTb4b4b4(Te6edf3rawMessageTb4b4b4: Tffa657StringTb4b4b4, Tff7b72vararg Te6edf3nodeIdsTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3msg Tff7b72= Te6edf3StringBuilderTb4b4b4(Te6edf3rawMessageTb4b4b4)
Tff7b72var Te6edf3mutated Tff7b72= Tff7b72false
Te6edf3nodeIdsTb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3nodeId Tff7b72-Tff7b72> Te6edf3mutated Tff7b72= Te6edf3mutated Te6edf3or Te6edf3msgTb4b4b4.Te6edf3annotateNodeIdTb4b4b4(Te6edf3nodeIdTb4b4b4) Tb4b4b4}
Tff7b72return Tff7b72if Tb4b4b4(Te6edf3mutatedTb4b4b4) Tb4b4b4{
Te6edf3msgTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3rawMessage
Tb4b4b4}
Tb4b4b4}
T8b949e/** Look for a single node ID integer in the string and annotate it with the hex equivalent if found. */
Tff7b72private Tff7b72fun Te6edf3StringBuilderTb4b4b4.Td2a8ffannotateNodeIdTb4b4b4(Te6edf3nodeIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3nodeIdStr Tff7b72= Te6edf3nodeIdTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)
T8b949e// Only match if whitespace before and after
Tff7b72val Te6edf3regex Tff7b72= Te6edf3RegexTb4b4b4(Ta5d6ff"""Ta5d6ff(?<=Ta5d6ff\Ta5d6ffs|^)Tffd700${Te6edf3RegexTb4b4b4.Te6edf3escapeTb4b4b4(Te6edf3nodeIdStrTb4b4b4)Tffd700}Ta5d6ff(?=Ta5d6ff\Ta5d6ffs|$Ta5d6ff)Ta5d6ff"""Tb4b4b4)
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3regexTb4b4b4.Te6edf3containsMatchInTb4b4b4(Tff7b72thisTb4b4b4)Tb4b4b4) Tff7b72return Tff7b72false
Te6edf3regexTb4b4b4.Te6edf3findAllTb4b4b4(Tff7b72thisTb4b4b4)Tb4b4b4.Te6edf3toListTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3asReversedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{
Tff7b72val Te6edf3idx Tff7b72= Tffa657itTb4b4b4.Te6edf3rangeTb4b4b4.Te6edf3last Tff7b72+ T79c0ff1
Te6edf3insertTb4b4b4(Te6edf3idxTb4b4b4, Ta5d6ff"Ta5d6ff (Tffd700${Te6edf3nodeIdTb4b4b4.Te6edf3toHexTb4b4b4(T79c0ff8Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72return Tff7b72true
Tb4b4b4}
Tff7b72private Tff7b72fun Te6edf3IntTb4b4b4.Td2a8fftoHexTb4b4b4(Te6edf3lengthTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff!Tffd700${Tff7b72thisTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(Te6edf3lengthTb4b4b4, Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff"
Tff7b72fun Td2a8ffrequestDeleteAllLogsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3alertManagerTb4b4b4.Te6edf3showAlertTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3debug_clearTb4b4b4,
Te6edf3messageRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3debug_clear_logs_confirmTb4b4b4,
Te6edf3onConfirm Tff7b72= Tb4b4b4{ Te6edf3deleteAllLogsTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffdeleteAllLogsTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3safeLaunchTb4b4b4(Te6edf3context Tff7b72= Te6edf3ioDispatcherTb4b4b4, Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffdeleteAllLogsTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteAllTb4b4b4(Tb4b4b4) Tb4b4b4}
Tf0883e@Immutable
Tff7b72data Tff7b72class T56d364UiMeshLogTb4b4b4(
Tff7b72val Te6edf3uuidTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3messageTypeTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3formattedReceivedDateTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3logMessageTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3decodedPayloadTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3presetFiltersTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3buildList Tb4b4b4{
T8b949e// Our address if available
Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNumTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3addTb4b4b4(Tffa657itTb4b4b4.Te6edf3toHexTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4) Tb4b4b4}
T8b949e// broadcast
Te6edf3addTb4b4b4(Ta5d6ff"Ta5d6ff!ffffffffTa5d6ff"Tb4b4b4)
T8b949e// decoded
Te6edf3addTb4b4b4(Ta5d6ff"Ta5d6ffdecodedTa5d6ff"Tb4b4b4)
T8b949e// today (locale-dependent short date format)
Te6edf3addTb4b4b4(Te6edf3DateFormatterTb4b4b4.Te6edf3formatShortDateTb4b4b4(Te6edf3nowInstantTb4b4b4.Te6edf3toEpochMillisecondsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
T8b949e// Each app name
Te6edf3addAllTb4b4b4(Te6edf3PortNumTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3name Tb4b4b4}Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffsetSelectedLogIdTb4b4b4(Te6edf3idTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3_selectedLogIdTb4b4b4.Te6edf3value Tff7b72= Te6edf3id
Tb4b4b4}
T8b949e/**
* Attempts to fully decode the payload of a MeshLog's MeshPacket using the appropriate protobuf definition, based
* on the portnum of the packet.
*
* For known portnums, the payload is parsed into its corresponding proto message and returned as a string. For text
* and alert messages, the payload is interpreted as UTF-8 text. For unknown portnums, the payload is shown as a hex
* string.
*
* @param log The MeshLog containing the packet and payload to decode.
* @return A human-readable string representation of the decoded payload, or an error message if decoding fails, or
* null if the log does not contain a decodable packet.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffCyclomaticComplexMethodTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffNestedBlockDepthTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffdecodePayloadFromMeshLogTb4b4b4(Te6edf3logTb4b4b4: Te6edf3MeshLogTb4b4b4)Tb4b4b4: Tffa657String? Tb4b4b4{
Tff7b72val Te6edf3packet Tff7b72= Te6edf3logTb4b4b4.Te6edf3meshPacket
Tff7b72val Te6edf3decoded Tff7b72= Te6edf3packetTff7b72?.Te6edf3decoded Tff7b72?: Tff7b72return Tff7b72null
Tff7b72val Te6edf3portnumValue Tff7b72= Te6edf3decodedTb4b4b4.Te6edf3portnumTb4b4b4.Te6edf3value
Tff7b72val Te6edf3payload Tff7b72= Te6edf3decodedTb4b4b4.Te6edf3payloadTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72try Tb4b4b4{
Tff7b72when Tb4b4b4(Te6edf3portnumValueTb4b4b4) Tb4b4b4{
Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APPTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3PortNumTb4b4b4.Te6edf3ALERT_APPTb4b4b4.Te6edf3valueTb4b4b4,
Tff7b72-Tff7b72> Te6edf3payloadTb4b4b4.Te6edf3decodeToStringTb4b4b4(Tb4b4b4)
Te6edf3PortNumTb4b4b4.Te6edf3POSITION_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3PositionTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3PositionTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode PositionTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3WAYPOINT_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3WaypointTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3WaypointTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode WaypointTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3NODEINFO_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3UserTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3UserTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode UserTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3TelemetryTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3TelemetryTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode TelemetryTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3ROUTING_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3RoutingTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3RoutingTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode RoutingTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3ADMIN_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3AdminMessageTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3AdminMessageTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode AdminMessageTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3PAXCOUNTER_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3PaxcountTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3PaxcountTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode PaxcountTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3STORE_FORWARD_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3StoreAndForwardTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3StoreAndForwardTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode StoreAndForwardTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3STORE_FORWARD_PLUSPLUS_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72>
Te6edf3StoreForwardPlusPlusTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeOrNullTb4b4b4(Te6edf3payloadTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{
Te6edf3StoreForwardPlusPlusTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3toReadableStringTb4b4b4(Tffa657itTb4b4b4)
Tb4b4b4} Tff7b72?: Ta5d6ff"Ta5d6ffFailed to decode StoreForwardPlusPlusTa5d6ff"
Te6edf3PortNumTb4b4b4.Te6edf3NEIGHBORINFO_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72> Te6edf3decodeNeighborInfoTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3PortNumTb4b4b4.Te6edf3TRACEROUTE_APPTb4b4b4.Te6edf3value Tff7b72-Tff7b72> Te6edf3decodeTracerouteTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3payloadTb4b4b4)
Tff7b72else Tff7b72-Tff7b72> Te6edf3payloadTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffFailed to decode payload: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff"
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Te6edf3ByteTb4b4b4.Td2a8fftoHexTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72thisTb4b4b4.Te6edf3toUByteTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffformatNodeWithShortNameTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3user Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3valueTff7b72[Te6edf3nodeNumTff7b72]Tff7b72?.Te6edf3user
Tff7b72val Te6edf3shortName Tff7b72= Te6edf3userTff7b72?.Te6edf3short_nameTff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tb4b4b4} Tff7b72?: Ta5d6ff"Ta5d6ff"
Tff7b72val Te6edf3nodeId Tff7b72= Te6edf3nodeNumTb4b4b4.Te6edf3toHexTb4b4b4(T79c0ff8Tb4b4b4)
Tff7b72return Tff7b72if Tb4b4b4(Te6edf3shortNameTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Ta5d6ff"Tffd700$Te6edf3nodeIdTa5d6ff (Tffd700$Te6edf3shortNameTa5d6ff)Ta5d6ff" Tff7b72else Te6edf3nodeId
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffdecodeNeighborInfoTb4b4b4(Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3info Tff7b72= Te6edf3NeighborInfoTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72return Te6edf3buildString Tb4b4b4{
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffNeighborInfo:Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ff node_id: Tffd700${Te6edf3formatNodeWithShortNameTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3node_idTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ff last_sent_by_id: Tffd700${Te6edf3formatNodeWithShortNameTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3last_sent_by_idTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ff node_broadcast_interval_secs: Tffd700${Te6edf3infoTb4b4b4.Te6edf3node_broadcast_interval_secsTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3neighborsTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ff neighbors:Ta5d6ff"Tb4b4b4)
Te6edf3infoTb4b4b4.Te6edf3neighborsTb4b4b4.Te6edf3forEach Tb4b4b4{
Te6edf3appendLineTb4b4b4(
Ta5d6ff"Ta5d6ff - node_id: Tffd700${Te6edf3formatNodeWithShortNameTb4b4b4(Tffa657itTb4b4b4.Te6edf3node_idTb4b4b4)Tffd700}Ta5d6ff snr: Tffd700${Te6edf3MetricFormatterTb4b4b4.Te6edf3snrTb4b4b4(Tffa657itTb4b4b4.Te6edf3snrTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffdecodeTracerouteTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4, Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3getUsernameTb4b4b4: Tb4b4b4(Tffa657IntTb4b4b4) Tff7b72-Tff7b72> Tffa657String Tff7b72= Tb4b4b4{ Te6edf3nodeNum Tff7b72-Tff7b72> Te6edf3formatNodeWithShortNameTb4b4b4(Te6edf3nodeNumTb4b4b4) Tb4b4b4}
Tff7b72return Te6edf3packetTb4b4b4.Te6edf3getTracerouteResponseTb4b4b4(Te6edf3getUsernameTb4b4b4)
Tff7b72?: Te6edf3runCatching Tb4b4b4{ Te6edf3RouteDiscoveryTb4b4b4.Te6edf3ADAPTERTb4b4b4.Te6edf3decodeTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3getOrNullTb4b4b4(Tb4b4b4)
Tff7b72?: Te6edf3payloadTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.23s